package com.aly.beanValidate.i;

import com.aly.beanValidate.core.BeanConfigs;
import com.aly.beanValidate.core.BeanDefinition;
import com.aly.beanValidate.core.FieldConfigs;
import com.aly.beanValidate.core.GlobalConfigs;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class BeanValidator {
    private final GlobalConfigs globalConfigs;
    private final BeanConfigs definitions;

    private BeanValidator(Document document) throws Exception {
        globalConfigs = GlobalConfigs.load(document);
        this.definitions = BeanConfigs.load(document, globalConfigs);
    }

    public static BeanValidator load(String configFileName) throws Exception {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(ClassLoader.getSystemResourceAsStream(configFileName));
        return new BeanValidator(document);
    }

    public String validateBean(FileInfos fileInfos) {
        StringBuilder sb = new StringBuilder();
        for (FileInfo fileInfo : fileInfos) {
            StringBuilder fileV = new StringBuilder();
            for (BeanInfo beanInfo : fileInfo) {
                StringBuffer ret = validateBean(beanInfo, fileInfo, fileInfos);
                if (null != ret) {
                    fileV.append(sb);
                }
            }
            if (fileV.length() > 0) {
                sb.append("文件[").append(fileInfo.getFileName()).append("] 校验出错:\n\t").append(fileV).append("\n");
            }
        }
        return sb.toString();
    }

    private StringBuffer validateBean(BeanInfo bean, FileInfo fileInfo, FileInfos fileInfos) {
        String fileName = fileInfo.getFileName();
        BeanDefinition definition = definitions.get(fileName);
        if (definition != null) {
            if (definition.getFileName().equals(fileName)) {
                return definition.validate(bean, fileInfo, fileInfos);
            } else {
                throw new RuntimeException("请检查文件定义名字: real:" + fileName + " inDefine:" + definition.getFileName());
            }
        }
        return null;
    }

    /**
     * 查看是否所有的检查都已经使用了
     */
    public StringBuffer checkNotUseValidator() {
        StringBuffer sb = new StringBuffer();
        List<String> notUseDefine = definitions.values().stream().filter(d -> d.getUseCount() <= 0)
                .map(d -> d.getDefinition().getFileName())
                .collect(Collectors.toList());
        if (notUseDefine.size() > 0) {
            sb.append("\n未使用的文件定义:").append(notUseDefine).append(", 请检查配置");
        }

        definitions.values().stream()
                .filter(define -> define.getUseCount() > 0)
                .map(BeanConfigs.BeanConfig::getDefinition)
                .forEach(define -> {
                    Map<String, FieldConfigs> map = define.getFieldValidators();
                    List<String> fields = new ArrayList<>();
                    for (FieldConfigs value : map.values()) {
                        if (value.getUseCount() == 0) {
                            fields.add(value.getDefinition().getFieldName());
                        }
                    }
                    if (fields.size() > 0) {
                        sb.append("\n\t").append(define.getFileName()).append("未使用的:").append(fields).append(", 请检查配置");
                    }
                });
        return sb;
    }

    public GlobalConfigs getGlobalConfigs() {
        return globalConfigs;
    }

    public BeanConfigs getDefinitions() {
        return definitions;
    }
}
